#ifndef THINK_THINK_TEMPLATE_H
#define THINK_THINK_TEMPLATE_H

static char* think_template =
	"\n"
	"// +----------------------------------------------------------------------\n"
	"// | ThinkPHP [ WE CAN DO IT JUST THINK ]\n"
	"// +----------------------------------------------------------------------\n"
	"// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.\n"
	"// +----------------------------------------------------------------------\n"
	"// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )\n"
	"// +----------------------------------------------------------------------\n"
	"// | Author: liu21st <liu21st@gmail.com>\n"
	"// +----------------------------------------------------------------------\n"
	"\n"
	"namespace think;\n"
	"\n"
	"use think\\exception\\TemplateNotFoundException;\n"
	"use think\\template\\TagLib;\n"
	"\n"
	"/**\n"
	" * ThinkPHP分离出来的模板引擎\n"
	" * 支持XML标签和普通标签的模板解析\n"
	" * 编译型模板引擎 支持动态缓存\n"
	" */\n"
	"class Template\n"
	"{\n"
	"    // 模板变量\n"
	"    protected $data = [];\n"
	"    // 引擎配置\n"
	"    protected $config = [\n"
	"        \'view_path\'          => \'\', // 模板路径\n"
	"        \'view_base\'          => \'\',\n"
	"        \'view_suffix\'        => \'html\', // 默认模板文件后缀\n"
	"        \'view_depr\'          => DS,\n"
	"        \'cache_suffix\'       => \'php\', // 默认模板缓存后缀\n"
	"        \'tpl_deny_func_list\' => \'echo,exit\', // 模板引擎禁用函数\n"
	"        \'tpl_deny_php\'       => false, // 默认模板引擎是否禁用PHP原生代码\n"
	"        \'tpl_begin\'          => \'{\', // 模板引擎普通标签开始标记\n"
	"        \'tpl_end\'            => \'}\', // 模板引擎普通标签结束标记\n"
	"        \'strip_space\'        => false, // 是否去除模板文件里面的html空格与换行\n"
	"        \'tpl_cache\'          => true, // 是否开启模板编译缓存,设为false则每次都会重新编译\n"
	"        \'compile_type\'       => \'file\', // 模板编译类型\n"
	"        \'cache_prefix\'       => \'\', // 模板缓存前缀标识，可以动态改变\n"
	"        \'cache_time\'         => 0, // 模板缓存有效期 0 为永久，(以数字为值，单位:秒)\n"
	"        \'layout_on\'          => false, // 布局模板开关\n"
	"        \'layout_name\'        => \'layout\', // 布局模板入口文件\n"
	"        \'layout_item\'        => \'{__CONTENT__}\', // 布局模板的内容替换标识\n"
	"        \'taglib_begin\'       => \'{\', // 标签库标签开始标记\n"
	"        \'taglib_end\'         => \'}\', // 标签库标签结束标记\n"
	"        \'taglib_load\'        => true, // 是否使用内置标签库之外的其它标签库，默认自动检测\n"
	"        \'taglib_build_in\'    => \'cx\', // 内置标签库名称(标签使用不必指定标签库名称),以逗号分隔 注意解析顺序\n"
	"        \'taglib_pre_load\'    => \'\', // 需要额外加载的标签库(须指定标签库名称)，多个以逗号分隔\n"
	"        \'display_cache\'      => false, // 模板渲染缓存\n"
	"        \'cache_id\'           => \'\', // 模板缓存ID\n"
	"        \'tpl_replace_string\' => [],\n"
	"        \'tpl_var_identify\'   => \'array\', // .语法变量识别，array|object|\'\', 为空时自动识别\n"
	"    ];\n"
	"\n"
	"    private $literal     = [];\n"
	"    private $includeFile = []; // 记录所有模板包含的文件路径及更新时间\n"
	"    protected $storage;\n"
	"\n"
	"    /**\n"
	"     * 构造函数\n"
	"     * @access public\n"
	"     * @param array $config\n"
	"     */\n"
	"    public function __construct(array $config = [])\n"
	"    {\n"
	"        $this->config[\'cache_path\'] = TEMP_PATH;\n"
	"        $this->config               = array_merge($this->config, $config);\n"
	"\n"
	"        $this->config[\'taglib_begin_origin\'] = $this->config[\'taglib_begin\'];\n"
	"        $this->config[\'taglib_end_origin\']   = $this->config[\'taglib_end\'];\n"
	"\n"
	"        $this->config[\'taglib_begin\'] = preg_quote($this->config[\'taglib_begin\'], \'/\');\n"
	"        $this->config[\'taglib_end\']   = preg_quote($this->config[\'taglib_end\'], \'/\');\n"
	"        $this->config[\'tpl_begin\']    = preg_quote($this->config[\'tpl_begin\'], \'/\');\n"
	"        $this->config[\'tpl_end\']      = preg_quote($this->config[\'tpl_end\'], \'/\');\n"
	"\n"
	"        // 初始化模板编译存储器\n"
	"        $type          = $this->config[\'compile_type\'] ? $this->config[\'compile_type\'] : \'File\';\n"
	"        $class         = false !== strpos($type, \'\\\\\') ? $type : \'\\\\think\\\\template\\\\driver\\\\\' . ucwords($type);\n"
	"        $this->storage = new $class();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 模板变量赋值\n"
	"     * @access public\n"
	"     * @param mixed $name\n"
	"     * @param mixed $value\n"
	"     * @return void\n"
	"     */\n"
	"    public function assign($name, $value = \'\')\n"
	"    {\n"
	"        if (is_array($name)) {\n"
	"            $this->data = array_merge($this->data, $name);\n"
	"        } else {\n"
	"            $this->data[$name] = $value;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 模板引擎参数赋值\n"
	"     * @access public\n"
	"     * @param mixed $name\n"
	"     * @param mixed $value\n"
	"     */\n"
	"    public function __set($name, $value)\n"
	"    {\n"
	"        $this->config[$name] = $value;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 模板引擎配置项\n"
	"     * @access public\n"
	"     * @param array|string $config\n"
	"     * @return string|void|array\n"
	"     */\n"
	"    public function config($config)\n"
	"    {\n"
	"        if (is_array($config)) {\n"
	"            $this->config = array_merge($this->config, $config);\n"
	"        } elseif (isset($this->config[$config])) {\n"
	"            return $this->config[$config];\n"
	"        } else {\n"
	"            return;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 模板变量获取\n"
	"     * @access public\n"
	"     * @param  string $name 变量名\n"
	"     * @return mixed\n"
	"     */\n"
	"    public function get($name = \'\')\n"
	"    {\n"
	"        if (\'\' == $name) {\n"
	"            return $this->data;\n"
	"        } else {\n"
	"            $data = $this->data;\n"
	"            foreach (explode(\'.\', $name) as $key => $val) {\n"
	"                if (isset($data[$val])) {\n"
	"                    $data = $data[$val];\n"
	"                } else {\n"
	"                    $data = null;\n"
	"                    break;\n"
	"                }\n"
	"            }\n"
	"            return $data;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 渲染模板文件\n"
	"     * @access public\n"
	"     * @param string    $template 模板文件\n"
	"     * @param array     $vars 模板变量\n"
	"     * @param array     $config 模板参数\n"
	"     * @return void\n"
	"     */\n"
	"    public function fetch($template, $vars = [], $config = [])\n"
	"    {\n"
	"        if ($vars) {\n"
	"            $this->data = $vars;\n"
	"        }\n"
	"        if ($config) {\n"
	"            $this->config($config);\n"
	"        }\n"
	"        if (!empty($this->config[\'cache_id\']) && $this->config[\'display_cache\']) {\n"
	"            // 读取渲染缓存\n"
	"            $cacheContent = Cache::get($this->config[\'cache_id\']);\n"
	"            if (false !== $cacheContent) {\n"
	"                echo $cacheContent;\n"
	"                return;\n"
	"            }\n"
	"        }\n"
	"        $template = $this->parseTemplateFile($template);\n"
	"        if ($template) {\n"
	"            $cacheFile = $this->config[\'cache_path\'] . $this->config[\'cache_prefix\'] . md5($this->config[\'layout_name\'] . $template) . \'.\' . ltrim($this->config[\'cache_suffix\'], \'.\');\n"
	"            if (!$this->checkCache($cacheFile)) {\n"
	"                // 缓存无效 重新模板编译\n"
	"                $content = file_get_contents($template);\n"
	"                $this->compiler($content, $cacheFile);\n"
	"            }\n"
	"            // 页面缓存\n"
	"            ob_start();\n"
	"            ob_implicit_flush(0);\n"
	"            // 读取编译存储\n"
	"            $this->storage->read($cacheFile, $this->data);\n"
	"            // 获取并清空缓存\n"
	"            $content = ob_get_clean();\n"
	"            if (!empty($this->config[\'cache_id\']) && $this->config[\'display_cache\']) {\n"
	"                // 缓存页面输出\n"
	"                Cache::set($this->config[\'cache_id\'], $content, $this->config[\'cache_time\']);\n"
	"            }\n"
	"            echo $content;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 渲染模板内容\n"
	"     * @access public\n"
	"     * @param string    $content 模板内容\n"
	"     * @param array     $vars 模板变量\n"
	"     * @param array     $config 模板参数\n"
	"     * @return void\n"
	"     */\n"
	"    public function display($content, $vars = [], $config = [])\n"
	"    {\n"
	"        if ($vars) {\n"
	"            $this->data = $vars;\n"
	"        }\n"
	"        if ($config) {\n"
	"            $this->config($config);\n"
	"        }\n"
	"        $cacheFile = $this->config[\'cache_path\'] . $this->config[\'cache_prefix\'] . md5($content) . \'.\' . ltrim($this->config[\'cache_suffix\'], \'.\');\n"
	"        if (!$this->checkCache($cacheFile)) {\n"
	"            // 缓存无效 模板编译\n"
	"            $this->compiler($content, $cacheFile);\n"
	"        }\n"
	"        // 读取编译存储\n"
	"        $this->storage->read($cacheFile, $this->data);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置布局\n"
	"     * @access public\n"
	"     * @param mixed     $name 布局模板名称 false 则关闭布局\n"
	"     * @param string    $replace 布局模板内容替换标识\n"
	"     * @return Template\n"
	"     */\n"
	"    public function layout($name, $replace = \'\')\n"
	"    {\n"
	"        if (false === $name) {\n"
	"            // 关闭布局\n"
	"            $this->config[\'layout_on\'] = false;\n"
	"        } else {\n"
	"            // 开启布局\n"
	"            $this->config[\'layout_on\'] = true;\n"
	"            // 名称必须为字符串\n"
	"            if (is_string($name)) {\n"
	"                $this->config[\'layout_name\'] = $name;\n"
	"            }\n"
	"            if (!empty($replace)) {\n"
	"                $this->config[\'layout_item\'] = $replace;\n"
	"            }\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检查编译缓存是否有效\n"
	"     * 如果无效则需要重新编译\n"
	"     * @access private\n"
	"     * @param string $cacheFile 缓存文件名\n"
	"     * @return boolean\n"
	"     */\n"
	"    private function checkCache($cacheFile)\n"
	"    {\n"
	"        // 未开启缓存功能\n"
	"        if (!$this->config[\'tpl_cache\']) {\n"
	"            return false;\n"
	"        }\n"
	"        // 缓存文件不存在\n"
	"        if (!is_file($cacheFile)) {\n"
	"            return false;\n"
	"        }\n"
	"        // 读取缓存文件失败\n"
	"        if (!$handle = @fopen($cacheFile, \"r\")) {\n"
	"            return false;\n"
	"        }\n"
	"        // 读取第一行\n"
	"        preg_match(\'/\\/\\*(.+?)\\*\\//\', fgets($handle), $matches);\n"
	"        if (!isset($matches[1])) {\n"
	"            return false;\n"
	"        }\n"
	"        $includeFile = unserialize($matches[1]);\n"
	"        if (!is_array($includeFile)) {\n"
	"            return false;\n"
	"        }\n"
	"        // 检查模板文件是否有更新\n"
	"        foreach ($includeFile as $path => $time) {\n"
	"            if (is_file($path) && filemtime($path) > $time) {\n"
	"                // 模板文件如果有更新则缓存需要更新\n"
	"                return false;\n"
	"            }\n"
	"        }\n"
	"        // 检查编译存储是否有效\n"
	"        return $this->storage->check($cacheFile, $this->config[\'cache_time\']);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检查编译缓存是否存在\n"
	"     * @access public\n"
	"     * @param string $cacheId 缓存的id\n"
	"     * @return boolean\n"
	"     */\n"
	"    public function isCache($cacheId)\n"
	"    {\n"
	"        if ($cacheId && $this->config[\'display_cache\']) {\n"
	"            // 缓存页面输出\n"
	"            return Cache::has($cacheId);\n"
	"        }\n"
	"        return false;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 编译模板文件内容\n"
	"     * @access private\n"
	"     * @param string    $content 模板内容\n"
	"     * @param string    $cacheFile 缓存文件名\n"
	"     * @return void\n"
	"     */\n"
	"    private function compiler(&$content, $cacheFile)\n"
	"    {\n"
	"        // 判断是否启用布局\n"
	"        if ($this->config[\'layout_on\']) {\n"
	"            if (false !== strpos($content, \'{__NOLAYOUT__}\')) {\n"
	"                // 可以单独定义不使用布局\n"
	"                $content = str_replace(\'{__NOLAYOUT__}\', \'\', $content);\n"
	"            } else {\n"
	"                // 读取布局模板\n"
	"                $layoutFile = $this->parseTemplateFile($this->config[\'layout_name\']);\n"
	"                if ($layoutFile) {\n"
	"                    // 替换布局的主体内容\n"
	"                    $content = str_replace($this->config[\'layout_item\'], $content, file_get_contents($layoutFile));\n"
	"                }\n"
	"            }\n"
	"        } else {\n"
	"            $content = str_replace(\'{__NOLAYOUT__}\', \'\', $content);\n"
	"        }\n"
	"\n"
	"        // 模板解析\n"
	"        $this->parse($content);\n"
	"        if ($this->config[\'strip_space\']) {\n"
	"            /* 去除html空格与换行 */\n"
	"            $find    = [\'~>\\s+<~\', \'~>(\\s+\\n|\\r)~\'];\n"
	"            $replace = [\'><\', \'>\'];\n"
	"            $content = preg_replace($find, $replace, $content);\n"
	"        }\n"
	"        // 优化生成的php代码\n"
	"        $content = preg_replace(\'/\\?>\\s*<\\?php\\s(?!echo\\b)/s\', \'\', $content);\n"
	"        // 模板过滤输出\n"
	"        $replace = $this->config[\'tpl_replace_string\'];\n"
	"        $content = str_replace(array_keys($replace), array_values($replace), $content);\n"
	"        // 添加安全代码及模板引用记录\n"
	"        $content = \'<?php if (!defined(\\\'THINK_PATH\\\')) exit(); /*\' . serialize($this->includeFile) . \'*/ ?>\' . \"\\n\" . $content;\n"
	"        // 编译存储\n"
	"        $this->storage->write($cacheFile, $content);\n"
	"        $this->includeFile = [];\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 模板解析入口\n"
	"     * 支持普通标签和TagLib解析 支持自定义标签库\n"
	"     * @access public\n"
	"     * @param string $content 要解析的模板内容\n"
	"     * @return void\n"
	"     */\n"
	"    public function parse(&$content)\n"
	"    {\n"
	"        // 内容为空不解析\n"
	"        if (empty($content)) {\n"
	"            return;\n"
	"        }\n"
	"        // 替换literal标签内容\n"
	"        $this->parseLiteral($content);\n"
	"        // 解析继承\n"
	"        $this->parseExtend($content);\n"
	"        // 解析布局\n"
	"        $this->parseLayout($content);\n"
	"        // 检查include语法\n"
	"        $this->parseInclude($content);\n"
	"        // 替换包含文件中literal标签内容\n"
	"        $this->parseLiteral($content);\n"
	"        // 检查PHP语法\n"
	"        $this->parsePhp($content);\n"
	"\n"
	"        // 获取需要引入的标签库列表\n"
	"        // 标签库只需要定义一次，允许引入多个一次\n"
	"        // 一般放在文件的最前面\n"
	"        // 格式：<taglib name=\"html,mytag...\" />\n"
	"        // 当TAGLIB_LOAD配置为true时才会进行检测\n"
	"        if ($this->config[\'taglib_load\']) {\n"
	"            $tagLibs = $this->getIncludeTagLib($content);\n"
	"            if (!empty($tagLibs)) {\n"
	"                // 对导入的TagLib进行解析\n"
	"                foreach ($tagLibs as $tagLibName) {\n"
	"                    $this->parseTagLib($tagLibName, $content);\n"
	"                }\n"
	"            }\n"
	"        }\n"
	"        // 预先加载的标签库 无需在每个模板中使用taglib标签加载 但必须使用标签库XML前缀\n"
	"        if ($this->config[\'taglib_pre_load\']) {\n"
	"            $tagLibs = explode(\',\', $this->config[\'taglib_pre_load\']);\n"
	"            foreach ($tagLibs as $tag) {\n"
	"                $this->parseTagLib($tag, $content);\n"
	"            }\n"
	"        }\n"
	"        // 内置标签库 无需使用taglib标签导入就可以使用 并且不需使用标签库XML前缀\n"
	"        $tagLibs = explode(\',\', $this->config[\'taglib_build_in\']);\n"
	"        foreach ($tagLibs as $tag) {\n"
	"            $this->parseTagLib($tag, $content, true);\n"
	"        }\n"
	"        // 解析普通模板标签 {$tagName}\n"
	"        $this->parseTag($content);\n"
	"\n"
	"        // 还原被替换的Literal标签\n"
	"        $this->parseLiteral($content, true);\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检查PHP语法\n"
	"     * @access private\n"
	"     * @param string $content 要解析的模板内容\n"
	"     * @return void\n"
	"     * @throws \\think\\Exception\n"
	"     */\n"
	"    private function parsePhp(&$content)\n"
	"    {\n"
	"        // 短标签的情况要将<?标签用echo方式输出 否则无法正常输出xml标识\n"
	"        $content = preg_replace(\'/(<\\?(?!php|=|$))/i\', \'<?php echo \\\'\\\\1\\\'; ?>\' . \"\\n\", $content);\n"
	"        // PHP语法检查\n"
	"        if ($this->config[\'tpl_deny_php\'] && false !== strpos($content, \'<?php\')) {\n"
	"            throw new Exception(\'not allow php tag\', 11600);\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 解析模板中的布局标签\n"
	"     * @access private\n"
	"     * @param string $content 要解析的模板内容\n"
	"     * @return void\n"
	"     */\n"
	"    private function parseLayout(&$content)\n"
	"    {\n"
	"        // 读取模板中的布局标签\n"
	"        if (preg_match($this->getRegex(\'layout\'), $content, $matches)) {\n"
	"            // 替换Layout标签\n"
	"            $content = str_replace($matches[0], \'\', $content);\n"
	"            // 解析Layout标签\n"
	"            $array = $this->parseAttr($matches[0]);\n"
	"            if (!$this->config[\'layout_on\'] || $this->config[\'layout_name\'] != $array[\'name\']) {\n"
	"                // 读取布局模板\n"
	"                $layoutFile = $this->parseTemplateFile($array[\'name\']);\n"
	"                if ($layoutFile) {\n"
	"                    $replace = isset($array[\'replace\']) ? $array[\'replace\'] : $this->config[\'layout_item\'];\n"
	"                    // 替换布局的主体内容\n"
	"                    $content = str_replace($replace, $content, file_get_contents($layoutFile));\n"
	"                }\n"
	"            }\n"
	"        } else {\n"
	"            $content = str_replace(\'{__NOLAYOUT__}\', \'\', $content);\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 解析模板中的include标签\n"
	"     * @access private\n"
	"     * @param  string $content 要解析的模板内容\n"
	"     * @return void\n"
	"     */\n"
	"    private function parseInclude(&$content)\n"
	"    {\n"
	"        $regex = $this->getRegex(\'include\');\n"
	"        $func  = function ($template) use (&$func, &$regex, &$content) {\n"
	"            if (preg_match_all($regex, $template, $matches, PREG_SET_ORDER)) {\n"
	"                foreach ($matches as $match) {\n"
	"                    $array = $this->parseAttr($match[0]);\n"
	"                    $file  = $array[\'file\'];\n"
	"                    unset($array[\'file\']);\n"
	"                    // 分析模板文件名并读取内容\n"
	"                    $parseStr = $this->parseTemplateName($file);\n"
	"                    foreach ($array as $k => $v) {\n"
	"                        // 以$开头字符串转换成模板变量\n"
	"                        if (0 === strpos($v, \'$\')) {\n"
	"                            $v = $this->get(substr($v, 1));\n"
	"                        }\n"
	"                        $parseStr = str_replace(\'[\' . $k . \']\', $v, $parseStr);\n"
	"                    }\n"
	"                    $content = str_replace($match[0], $parseStr, $content);\n"
	"                    // 再次对包含文件进行模板分析\n"
	"                    $func($parseStr);\n"
	"                }\n"
	"                unset($matches);\n"
	"            }\n"
	"        };\n"
	"        // 替换模板中的include标签\n"
	"        $func($content);\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 解析模板中的extend标签\n"
	"     * @access private\n"
	"     * @param  string $content 要解析的模板内容\n"
	"     * @return void\n"
	"     */\n"
	"    private function parseExtend(&$content)\n"
	"    {\n"
	"        $regex  = $this->getRegex(\'extend\');\n"
	"        $array  = $blocks  = $baseBlocks  = [];\n"
	"        $extend = \'\';\n"
	"        $func   = function ($template) use (&$func, &$regex, &$array, &$extend, &$blocks, &$baseBlocks) {\n"
	"            if (preg_match($regex, $template, $matches)) {\n"
	"                if (!isset($array[$matches[\'name\']])) {\n"
	"                    $array[$matches[\'name\']] = 1;\n"
	"                    // 读取继承模板\n"
	"                    $extend = $this->parseTemplateName($matches[\'name\']);\n"
	"                    // 递归检查继承\n"
	"                    $func($extend);\n"
	"                    // 取得block标签内容\n"
	"                    $blocks = array_merge($blocks, $this->parseBlock($template));\n"
	"                    return;\n"
	"                }\n"
	"            } else {\n"
	"                // 取得顶层模板block标签内容\n"
	"                $baseBlocks = $this->parseBlock($template, true);\n"
	"                if (empty($extend)) {\n"
	"                    // 无extend标签但有block标签的情况\n"
	"                    $extend = $template;\n"
	"                }\n"
	"            }\n"
	"        };\n"
	"\n"
	"        $func($content);\n"
	"        if (!empty($extend)) {\n"
	"            if ($baseBlocks) {\n"
	"                $children = [];\n"
	"                foreach ($baseBlocks as $name => $val) {\n"
	"                    $replace = $val[\'content\'];\n"
	"                    if (!empty($children[$name])) {\n"
	"                        // 如果包含有子block标签\n"
	"                        foreach ($children[$name] as $key) {\n"
	"                            $replace = str_replace($baseBlocks[$key][\'begin\'] . $baseBlocks[$key][\'content\'] . $baseBlocks[$key][\'end\'], $blocks[$key][\'content\'], $replace);\n"
	"                        }\n"
	"                    }\n"
	"                    if (isset($blocks[$name])) {\n"
	"                        // 带有{__block__}表示与所继承模板的相应标签合并，而不是覆盖\n"
	"                        $replace = str_replace([\'{__BLOCK__}\', \'{__block__}\'], $replace, $blocks[$name][\'content\']);\n"
	"                        if (!empty($val[\'parent\'])) {\n"
	"                            // 如果不是最顶层的block标签\n"
	"                            $parent = $val[\'parent\'];\n"
	"                            if (isset($blocks[$parent])) {\n"
	"                                $blocks[$parent][\'content\'] = str_replace($blocks[$name][\'begin\'] . $blocks[$name][\'content\'] . $blocks[$name][\'end\'], $replace, $blocks[$parent][\'content\']);\n"
	"                            }\n"
	"                            $blocks[$name][\'content\'] = $replace;\n"
	"                            $children[$parent][]      = $name;\n"
	"                            continue;\n"
	"                        }\n"
	"                    } elseif (!empty($val[\'parent\'])) {\n"
	"                        // 如果子标签没有被继承则用原值\n"
	"                        $children[$val[\'parent\']][] = $name;\n"
	"                        $blocks[$name]              = $val;\n"
	"                    }\n"
	"                    if (!$val[\'parent\']) {\n"
	"                        // 替换模板中的顶级block标签\n"
	"                        $extend = str_replace($val[\'begin\'] . $val[\'content\'] . $val[\'end\'], $replace, $extend);\n"
	"                    }\n"
	"                }\n"
	"            }\n"
	"            $content = $extend;\n"
	"            unset($blocks, $baseBlocks);\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 替换页面中的literal标签\n"
	"     * @access private\n"
	"     * @param  string   $content 模板内容\n"
	"     * @param  boolean  $restore 是否为还原\n"
	"     * @return void\n"
	"     */\n"
	"    private function parseLiteral(&$content, $restore = false)\n"
	"    {\n"
	"        $regex = $this->getRegex($restore ? \'restoreliteral\' : \'literal\');\n"
	"        if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {\n"
	"            if (!$restore) {\n"
	"                $count = count($this->literal);\n"
	"                // 替换literal标签\n"
	"                foreach ($matches as $match) {\n"
	"                    $this->literal[] = substr($match[0], strlen($match[1]), -strlen($match[2]));\n"
	"                    $content         = str_replace($match[0], \"<!--###literal{$count}###-->\", $content);\n"
	"                    $count++;\n"
	"                }\n"
	"            } else {\n"
	"                // 还原literal标签\n"
	"                foreach ($matches as $match) {\n"
	"                    $content = str_replace($match[0], $this->literal[$match[1]], $content);\n"
	"                }\n"
	"                // 清空literal记录\n"
	"                $this->literal = [];\n"
	"            }\n"
	"            unset($matches);\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取模板中的block标签\n"
	"     * @access private\n"
	"     * @param  string   $content 模板内容\n"
	"     * @param  boolean  $sort 是否排序\n"
	"     * @return array\n"
	"     */\n"
	"    private function parseBlock(&$content, $sort = false)\n"
	"    {\n"
	"        $regex  = $this->getRegex(\'block\');\n"
	"        $result = [];\n"
	"        if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) {\n"
	"            $right = $keys = [];\n"
	"            foreach ($matches as $match) {\n"
	"                if (empty($match[\'name\'][0])) {\n"
	"                    if (count($right) > 0) {\n"
	"                        $tag                  = array_pop($right);\n"
	"                        $start                = $tag[\'offset\'] + strlen($tag[\'tag\']);\n"
	"                        $length               = $match[0][1] - $start;\n"
	"                        $result[$tag[\'name\']] = [\n"
	"                            \'begin\'   => $tag[\'tag\'],\n"
	"                            \'content\' => substr($content, $start, $length),\n"
	"                            \'end\'     => $match[0][0],\n"
	"                            \'parent\'  => count($right) ? end($right)[\'name\'] : \'\',\n"
	"                        ];\n"
	"                        $keys[$tag[\'name\']] = $match[0][1];\n"
	"                    }\n"
	"                } else {\n"
	"                    // 标签头压入栈\n"
	"                    $right[] = [\n"
	"                        \'name\'   => $match[2][0],\n"
	"                        \'offset\' => $match[0][1],\n"
	"                        \'tag\'    => $match[0][0],\n"
	"                    ];\n"
	"                }\n"
	"            }\n"
	"            unset($right, $matches);\n"
	"            if ($sort) {\n"
	"                // 按block标签结束符在模板中的位置排序\n"
	"                array_multisort($keys, $result);\n"
	"            }\n"
	"        }\n"
	"        return $result;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 搜索模板页面中包含的TagLib库\n"
	"     * 并返回列表\n"
	"     * @access private\n"
	"     * @param  string $content 模板内容\n"
	"     * @return array|null\n"
	"     */\n"
	"    private function getIncludeTagLib(&$content)\n"
	"    {\n"
	"        // 搜索是否有TagLib标签\n"
	"        if (preg_match($this->getRegex(\'taglib\'), $content, $matches)) {\n"
	"            // 替换TagLib标签\n"
	"            $content = str_replace($matches[0], \'\', $content);\n"
	"            return explode(\',\', $matches[\'name\']);\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * TagLib库解析\n"
	"     * @access public\n"
	"     * @param  string   $tagLib 要解析的标签库\n"
	"     * @param  string   $content 要解析的模板内容\n"
	"     * @param  boolean  $hide 是否隐藏标签库前缀\n"
	"     * @return void\n"
	"     */\n"
	"    public function parseTagLib($tagLib, &$content, $hide = false)\n"
	"    {\n"
	"        if (false !== strpos($tagLib, \'\\\\\')) {\n"
	"            // 支持指定标签库的命名空间\n"
	"            $className = $tagLib;\n"
	"            $tagLib    = substr($tagLib, strrpos($tagLib, \'\\\\\') + 1);\n"
	"        } else {\n"
	"            $className = \'\\\\think\\\\template\\\\taglib\\\\\' . ucwords($tagLib);\n"
	"        }\n"
	"        /** @var Taglib $tLib */\n"
	"        $tLib = new $className($this);\n"
	"        $tLib->parseTag($content, $hide ? \'\' : $tagLib);\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 分析标签属性\n"
	"     * @access public\n"
	"     * @param  string   $str 属性字符串\n"
	"     * @param  string   $name 不为空时返回指定的属性名\n"
	"     * @return array\n"
	"     */\n"
	"    public function parseAttr($str, $name = null)\n"
	"    {\n"
	"        $regex = \'/\\s+(?>(?P<name>[\\w-]+)\\s*)=(?>\\s*)([\\\"\\\'])(?P<value>(?:(?!\\\\2).)*)\\\\2/is\';\n"
	"        $array = [];\n"
	"        if (preg_match_all($regex, $str, $matches, PREG_SET_ORDER)) {\n"
	"            foreach ($matches as $match) {\n"
	"                $array[$match[\'name\']] = $match[\'value\'];\n"
	"            }\n"
	"            unset($matches);\n"
	"        }\n"
	"        if (!empty($name) && isset($array[$name])) {\n"
	"            return $array[$name];\n"
	"        } else {\n"
	"            return $array;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 模板标签解析\n"
	"     * 格式： {TagName:args [|content] }\n"
	"     * @access private\n"
	"     * @param  string $content 要解析的模板内容\n"
	"     * @return void\n"
	"     */\n"
	"    private function parseTag(&$content)\n"
	"    {\n"
	"        $regex = $this->getRegex(\'tag\');\n"
	"        if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {\n"
	"            foreach ($matches as $match) {\n"
	"                $str  = stripslashes($match[1]);\n"
	"                $flag = substr($str, 0, 1);\n"
	"                switch ($flag) {\n"
	"                    case \'$\':\n"
	"                        // 解析模板变量 格式 {$varName}\n"
	"                        // 是否带有?号\n"
	"                        if (false !== $pos = strpos($str, \'?\')) {\n"
	"                            $array = preg_split(\'/([!=]={1,2}|(?<!-)[><]={0,1})/\', substr($str, 0, $pos), 2, PREG_SPLIT_DELIM_CAPTURE);\n"
	"                            $name  = $array[0];\n"
	"                            $this->parseVar($name);\n"
	"                            $this->parseVarFunction($name);\n"
	"\n"
	"                            $str = trim(substr($str, $pos + 1));\n"
	"                            $this->parseVar($str);\n"
	"                            $first = substr($str, 0, 1);\n"
	"                            if (strpos($name, \')\')) {\n"
	"                                // $name为对象或是自动识别，或者含有函数\n"
	"                                if (isset($array[1])) {\n"
	"                                    $this->parseVar($array[2]);\n"
	"                                    $name .= $array[1] . $array[2];\n"
	"                                }\n"
	"                                switch ($first) {\n"
	"                                    case \'?\':\n"
	"                                        $str = \'<?php echo (\' . $name . \') ? \' . $name . \' : \' . substr($str, 1) . \'; ?>\';\n"
	"                                        break;\n"
	"                                    case \'=\':\n"
	"                                        $str = \'<?php if(\' . $name . \') echo \' . substr($str, 1) . \'; ?>\';\n"
	"                                        break;\n"
	"                                    default:\n"
	"                                        $str = \'<?php echo \' . $name . \'?\' . $str . \'; ?>\';\n"
	"                                }\n"
	"                            } else {\n"
	"                                if (isset($array[1])) {\n"
	"                                    $this->parseVar($array[2]);\n"
	"                                    $express = $name . $array[1] . $array[2];\n"
	"                                } else {\n"
	"                                    $express = false;\n"
	"                                }\n"
	"                                // $name为数组\n"
	"                                switch ($first) {\n"
	"                                    case \'?\':\n"
	"                                        // {$varname??\'xxx\'} $varname有定义则输出$varname,否则输出xxx\n"
	"                                        $str = \'<?php echo \' . ($express ?: \'isset(\' . $name . \')\') . \'?\' . $name . \':\' . substr($str, 1) . \'; ?>\';\n"
	"                                        break;\n"
	"                                    case \'=\':\n"
	"                                        // {$varname?=\'xxx\'} $varname为真时才输出xxx\n"
	"                                        $str = \'<?php if(\' . ($express ?: \'!empty(\' . $name . \')\') . \') echo \' . substr($str, 1) . \'; ?>\';\n"
	"                                        break;\n"
	"                                    case \':\':\n"
	"                                        // {$varname?:\'xxx\'} $varname为真时输出$varname,否则输出xxx\n"
	"                                        $str = \'<?php echo \' . ($express ?: \'!empty(\' . $name . \')\') . \'?\' . $name . $str . \'; ?>\';\n"
	"                                        break;\n"
	"                                    default:\n"
	"                                        $str = \'<?php echo \' . ($express ?: \'!empty(\' . $name . \')\') . \'?\' . $str . \'; ?>\';\n"
	"                                }\n"
	"                            }\n"
	"                        } else {\n"
	"                            $this->parseVar($str);\n"
	"                            $this->parseVarFunction($str);\n"
	"                            $str = \'<?php echo \' . $str . \'; ?>\';\n"
	"                        }\n"
	"                        break;\n"
	"                    case \':\':\n"
	"                        // 输出某个函数的结果\n"
	"                        $str = substr($str, 1);\n"
	"                        $this->parseVar($str);\n"
	"                        $str = \'<?php echo \' . $str . \'; ?>\';\n"
	"                        break;\n"
	"                    case \'~\':\n"
	"                        // 执行某个函数\n"
	"                        $str = substr($str, 1);\n"
	"                        $this->parseVar($str);\n"
	"                        $str = \'<?php \' . $str . \'; ?>\';\n"
	"                        break;\n"
	"                    case \'-\':\n"
	"                    case \'+\':\n"
	"                        // 输出计算\n"
	"                        $this->parseVar($str);\n"
	"                        $str = \'<?php echo \' . $str . \'; ?>\';\n"
	"                        break;\n"
	"                    case \'/\':\n"
	"                        // 注释标签\n"
	"                        $flag2 = substr($str, 1, 1);\n"
	"                        if (\'/\' == $flag2 || (\'*\' == $flag2 && substr(rtrim($str), -2) == \'*/\')) {\n"
	"                            $str = \'\';\n"
	"                        }\n"
	"                        break;\n"
	"                    default:\n"
	"                        // 未识别的标签直接返回\n"
	"                        $str = $this->config[\'tpl_begin\'] . $str . $this->config[\'tpl_end\'];\n"
	"                        break;\n"
	"                }\n"
	"                $content = str_replace($match[0], $str, $content);\n"
	"            }\n"
	"            unset($matches);\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 模板变量解析,支持使用函数\n"
	"     * 格式： {$varname|function1|function2=arg1,arg2}\n"
	"     * @access public\n"
	"     * @param  string $varStr 变量数据\n"
	"     * @return void\n"
	"     */\n"
	"    public function parseVar(&$varStr)\n"
	"    {\n"
	"        $varStr = trim($varStr);\n"
	"        if (preg_match_all(\'/\\$[a-zA-Z_](?>\\w*)(?:[:\\.][0-9a-zA-Z_](?>\\w*))+/\', $varStr, $matches, PREG_OFFSET_CAPTURE)) {\n"
	"            static $_varParseList = [];\n"
	"            while ($matches[0]) {\n"
	"                $match = array_pop($matches[0]);\n"
	"                //如果已经解析过该变量字串，则直接返回变量值\n"
	"                if (isset($_varParseList[$match[0]])) {\n"
	"                    $parseStr = $_varParseList[$match[0]];\n"
	"                } else {\n"
	"                    if (strpos($match[0], \'.\')) {\n"
	"                        $vars  = explode(\'.\', $match[0]);\n"
	"                        $first = array_shift($vars);\n"
	"                        if (\'$Think\' == $first) {\n"
	"                            // 所有以Think.打头的以特殊变量对待 无需模板赋值就可以输出\n"
	"                            $parseStr = $this->parseThinkVar($vars);\n"
	"                        } elseif (\'$Request\' == $first) {\n"
	"                            // 获取Request请求对象参数\n"
	"                            $method = array_shift($vars);\n"
	"                            if (!empty($vars)) {\n"
	"                                $params = implode(\'.\', $vars);\n"
	"                                if (\'true\' != $params) {\n"
	"                                    $params = \'\\\'\' . $params . \'\\\'\';\n"
	"                                }\n"
	"                            } else {\n"
	"                                $params = \'\';\n"
	"                            }\n"
	"                            $parseStr = \'\\think\\Request::instance()->\' . $method . \'(\' . $params . \')\';\n"
	"                        } else {\n"
	"                            switch ($this->config[\'tpl_var_identify\']) {\n"
	"                                case \'array\': // 识别为数组\n"
	"                                    $parseStr = $first . \'[\\\'\' . implode(\'\\\'][\\\'\', $vars) . \'\\\']\';\n"
	"                                    break;\n"
	"                                case \'obj\': // 识别为对象\n"
	"                                    $parseStr = $first . \'->\' . implode(\'->\', $vars);\n"
	"                                    break;\n"
	"                                default: // 自动判断数组或对象\n"
	"                                    $parseStr = \'(is_array(\' . $first . \')?\' . $first . \'[\\\'\' . implode(\'\\\'][\\\'\', $vars) . \'\\\']:\' . $first . \'->\' . implode(\'->\', $vars) . \')\';\n"
	"                            }\n"
	"                        }\n"
	"                    } else {\n"
	"                        $parseStr = str_replace(\':\', \'->\', $match[0]);\n"
	"                    }\n"
	"                    $_varParseList[$match[0]] = $parseStr;\n"
	"                }\n"
	"                $varStr = substr_replace($varStr, $parseStr, $match[1], strlen($match[0]));\n"
	"            }\n"
	"            unset($matches);\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 对模板中使用了函数的变量进行解析\n"
	"     * 格式 {$varname|function1|function2=arg1,arg2}\n"
	"     * @access public\n"
	"     * @param  string $varStr 变量字符串\n"
	"     * @return void\n"
	"     */\n"
	"    public function parseVarFunction(&$varStr)\n"
	"    {\n"
	"        if (false == strpos($varStr, \'|\')) {\n"
	"            return;\n"
	"        }\n"
	"        static $_varFunctionList = [];\n"
	"        $_key                    = md5($varStr);\n"
	"        //如果已经解析过该变量字串，则直接返回变量值\n"
	"        if (isset($_varFunctionList[$_key])) {\n"
	"            $varStr = $_varFunctionList[$_key];\n"
	"        } else {\n"
	"            $varArray = explode(\'|\', $varStr);\n"
	"            // 取得变量名称\n"
	"            $name = array_shift($varArray);\n"
	"            // 对变量使用函数\n"
	"            $length = count($varArray);\n"
	"            // 取得模板禁止使用函数列表\n"
	"            $template_deny_funs = explode(\',\', $this->config[\'tpl_deny_func_list\']);\n"
	"            for ($i = 0; $i < $length; $i++) {\n"
	"                $args = explode(\'=\', $varArray[$i], 2);\n"
	"                // 模板函数过滤\n"
	"                $fun = trim($args[0]);\n"
	"                switch ($fun) {\n"
	"                    case \'default\': // 特殊模板函数\n"
	"                        if (false === strpos($name, \'(\')) {\n"
	"                            $name = \'(isset(\' . $name . \') && (\' . $name . \' !== \\\'\\\')?\' . $name . \':\' . $args[1] . \')\';\n"
	"                        } else {\n"
	"                            $name = \'(\' . $name . \' ?: \' . $args[1] . \')\';\n"
	"                        }\n"
	"                        break;\n"
	"                    default: // 通用模板函数\n"
	"                        if (!in_array($fun, $template_deny_funs)) {\n"
	"                            if (isset($args[1])) {\n"
	"                                if (strstr($args[1], \'###\')) {\n"
	"                                    $args[1] = str_replace(\'###\', $name, $args[1]);\n"
	"                                    $name    = \"$fun($args[1])\";\n"
	"                                } else {\n"
	"                                    $name = \"$fun($name,$args[1])\";\n"
	"                                }\n"
	"                            } else {\n"
	"                                if (!empty($args[0])) {\n"
	"                                    $name = \"$fun($name)\";\n"
	"                                }\n"
	"                            }\n"
	"                        }\n"
	"                }\n"
	"            }\n"
	"            $_varFunctionList[$_key] = $name;\n"
	"            $varStr                  = $name;\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 特殊模板变量解析\n"
	"     * 格式 以 $Think. 打头的变量属于特殊模板变量\n"
	"     * @access public\n"
	"     * @param  array $vars 变量数组\n"
	"     * @return string\n"
	"     */\n"
	"    public function parseThinkVar($vars)\n"
	"    {\n"
	"        $type  = strtoupper(trim(array_shift($vars)));\n"
	"        $param = implode(\'.\', $vars);\n"
	"        if ($vars) {\n"
	"            switch ($type) {\n"
	"                case \'SERVER\':\n"
	"                    $parseStr = \'\\\\think\\\\Request::instance()->server(\\\'\' . $param . \'\\\')\';\n"
	"                    break;\n"
	"                case \'GET\':\n"
	"                    $parseStr = \'\\\\think\\\\Request::instance()->get(\\\'\' . $param . \'\\\')\';\n"
	"                    break;\n"
	"                case \'POST\':\n"
	"                    $parseStr = \'\\\\think\\\\Request::instance()->post(\\\'\' . $param . \'\\\')\';\n"
	"                    break;\n"
	"                case \'COOKIE\':\n"
	"                    $parseStr = \'\\\\think\\\\Cookie::get(\\\'\' . $param . \'\\\')\';\n"
	"                    break;\n"
	"                case \'SESSION\':\n"
	"                    $parseStr = \'\\\\think\\\\Session::get(\\\'\' . $param . \'\\\')\';\n"
	"                    break;\n"
	"                case \'ENV\':\n"
	"                    $parseStr = \'\\\\think\\\\Request::instance()->env(\\\'\' . $param . \'\\\')\';\n"
	"                    break;\n"
	"                case \'REQUEST\':\n"
	"                    $parseStr = \'\\\\think\\\\Request::instance()->request(\\\'\' . $param . \'\\\')\';\n"
	"                    break;\n"
	"                case \'CONST\':\n"
	"                    $parseStr = strtoupper($param);\n"
	"                    break;\n"
	"                case \'LANG\':\n"
	"                    $parseStr = \'\\\\think\\\\Lang::get(\\\'\' . $param . \'\\\')\';\n"
	"                    break;\n"
	"                case \'CONFIG\':\n"
	"                    $parseStr = \'\\\\think\\\\Config::get(\\\'\' . $param . \'\\\')\';\n"
	"                    break;\n"
	"                default:\n"
	"                    $parseStr = \'\\\'\\\'\';\n"
	"                    break;\n"
	"            }\n"
	"        } else {\n"
	"            switch ($type) {\n"
	"                case \'NOW\':\n"
	"                    $parseStr = \"date(\'Y-m-d g:i a\',time())\";\n"
	"                    break;\n"
	"                case \'VERSION\':\n"
	"                    $parseStr = \'THINK_VERSION\';\n"
	"                    break;\n"
	"                case \'LDELIM\':\n"
	"                    $parseStr = \'\\\'\' . ltrim($this->config[\'tpl_begin\'], \'\\\\\') . \'\\\'\';\n"
	"                    break;\n"
	"                case \'RDELIM\':\n"
	"                    $parseStr = \'\\\'\' . ltrim($this->config[\'tpl_end\'], \'\\\\\') . \'\\\'\';\n"
	"                    break;\n"
	"                default:\n"
	"                    if (defined($type)) {\n"
	"                        $parseStr = $type;\n"
	"                    } else {\n"
	"                        $parseStr = \'\';\n"
	"                    }\n"
	"            }\n"
	"        }\n"
	"        return $parseStr;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 分析加载的模板文件并读取内容 支持多个模板文件读取\n"
	"     * @access private\n"
	"     * @param  string $templateName 模板文件名\n"
	"     * @return string\n"
	"     */\n"
	"    private function parseTemplateName($templateName)\n"
	"    {\n"
	"        $array    = explode(\',\', $templateName);\n"
	"        $parseStr = \'\';\n"
	"        foreach ($array as $templateName) {\n"
	"            if (empty($templateName)) {\n"
	"                continue;\n"
	"            }\n"
	"            if (0 === strpos($templateName, \'$\')) {\n"
	"                //支持加载变量文件名\n"
	"                $templateName = $this->get(substr($templateName, 1));\n"
	"            }\n"
	"            $template = $this->parseTemplateFile($templateName);\n"
	"            if ($template) {\n"
	"                // 获取模板文件内容\n"
	"                $parseStr .= file_get_contents($template);\n"
	"            }\n"
	"        }\n"
	"        return $parseStr;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 解析模板文件名\n"
	"     * @access private\n"
	"     * @param  string $template 文件名\n"
	"     * @return string|false\n"
	"     */\n"
	"    private function parseTemplateFile($template)\n"
	"    {\n"
	"        if (\'\' == pathinfo($template, PATHINFO_EXTENSION)) {\n"
	"            if (strpos($template, \'@\')) {\n"
	"                list($module, $template) = explode(\'@\', $template);\n"
	"            }\n"
	"            if (0 !== strpos($template, \'/\')) {\n"
	"                $template = str_replace([\'/\', \':\'], $this->config[\'view_depr\'], $template);\n"
	"            } else {\n"
	"                $template = str_replace([\'/\', \':\'], $this->config[\'view_depr\'], substr($template, 1));\n"
	"            }\n"
	"            if ($this->config[\'view_base\']) {\n"
	"                $module = isset($module) ? $module : Request::instance()->module();\n"
	"                $path   = $this->config[\'view_base\'] . ($module ? $module . DS : \'\');\n"
	"            } else {\n"
	"                $path = isset($module) ? APP_PATH . $module . DS . basename($this->config[\'view_path\']) . DS : $this->config[\'view_path\'];\n"
	"            }\n"
	"            $template = realpath($path . $template . \'.\' . ltrim($this->config[\'view_suffix\'], \'.\'));\n"
	"        }\n"
	"\n"
	"        if (is_file($template)) {\n"
	"            // 记录模板文件的更新时间\n"
	"            $this->includeFile[$template] = filemtime($template);\n"
	"            return $template;\n"
	"        } else {\n"
	"            throw new TemplateNotFoundException(\'template not exists:\' . $template, $template);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 按标签生成正则\n"
	"     * @access private\n"
	"     * @param  string $tagName 标签名\n"
	"     * @return string\n"
	"     */\n"
	"    private function getRegex($tagName)\n"
	"    {\n"
	"        $regex = \'\';\n"
	"        if (\'tag\' == $tagName) {\n"
	"            $begin = $this->config[\'tpl_begin\'];\n"
	"            $end   = $this->config[\'tpl_end\'];\n"
	"            if (strlen(ltrim($begin, \'\\\\\')) == 1 && strlen(ltrim($end, \'\\\\\')) == 1) {\n"
	"                $regex = $begin . \'((?:[\\$]{1,2}[a-wA-w_]|[\\:\\~][\\$a-wA-w_]|[+]{2}[\\$][a-wA-w_]|[-]{2}[\\$][a-wA-w_]|\\/[\\*\\/])(?>[^\' . $end . \']*))\' . $end;\n"
	"            } else {\n"
	"                $regex = $begin . \'((?:[\\$]{1,2}[a-wA-w_]|[\\:\\~][\\$a-wA-w_]|[+]{2}[\\$][a-wA-w_]|[-]{2}[\\$][a-wA-w_]|\\/[\\*\\/])(?>(?:(?!\' . $end . \').)*))\' . $end;\n"
	"            }\n"
	"        } else {\n"
	"            $begin  = $this->config[\'taglib_begin\'];\n"
	"            $end    = $this->config[\'taglib_end\'];\n"
	"            $single = strlen(ltrim($begin, \'\\\\\')) == 1 && strlen(ltrim($end, \'\\\\\')) == 1 ? true : false;\n"
	"            switch ($tagName) {\n"
	"                case \'block\':\n"
	"                    if ($single) {\n"
	"                        $regex = $begin . \'(?:\' . $tagName . \'\\b(?>(?:(?!name=).)*)\\bname=([\\\'\\\"])(?P<name>[\\$\\w\\-\\/\\.]+)\\\\1(?>[^\' . $end . \']*)|\\/\' . $tagName . \')\' . $end;\n"
	"                    } else {\n"
	"                        $regex = $begin . \'(?:\' . $tagName . \'\\b(?>(?:(?!name=).)*)\\bname=([\\\'\\\"])(?P<name>[\\$\\w\\-\\/\\.]+)\\\\1(?>(?:(?!\' . $end . \').)*)|\\/\' . $tagName . \')\' . $end;\n"
	"                    }\n"
	"                    break;\n"
	"                case \'literal\':\n"
	"                    if ($single) {\n"
	"                        $regex = \'(\' . $begin . $tagName . \'\\b(?>[^\' . $end . \']*)\' . $end . \')\';\n"
	"                        $regex .= \'(?:(?>[^\' . $begin . \']*)(?>(?!\' . $begin . \'(?>\' . $tagName . \'\\b[^\' . $end . \']*|\\/\' . $tagName . \')\' . $end . \')\' . $begin . \'[^\' . $begin . \']*)*)\';\n"
	"                        $regex .= \'(\' . $begin . \'\\/\' . $tagName . $end . \')\';\n"
	"                    } else {\n"
	"                        $regex = \'(\' . $begin . $tagName . \'\\b(?>(?:(?!\' . $end . \').)*)\' . $end . \')\';\n"
	"                        $regex .= \'(?:(?>(?:(?!\' . $begin . \').)*)(?>(?!\' . $begin . \'(?>\' . $tagName . \'\\b(?>(?:(?!\' . $end . \').)*)|\\/\' . $tagName . \')\' . $end . \')\' . $begin . \'(?>(?:(?!\' . $begin . \').)*))*)\';\n"
	"                        $regex .= \'(\' . $begin . \'\\/\' . $tagName . $end . \')\';\n"
	"                    }\n"
	"                    break;\n"
	"                case \'restoreliteral\':\n"
	"                    $regex = \'<!--###literal(\\d+)###-->\';\n"
	"                    break;\n"
	"                case \'include\':\n"
	"                    $name = \'file\';\n"
	"                case \'taglib\':\n"
	"                case \'layout\':\n"
	"                case \'extend\':\n"
	"                    if (empty($name)) {\n"
	"                        $name = \'name\';\n"
	"                    }\n"
	"                    if ($single) {\n"
	"                        $regex = $begin . $tagName . \'\\b(?>(?:(?!\' . $name . \'=).)*)\\b\' . $name . \'=([\\\'\\\"])(?P<name>[\\$\\w\\-\\/\\.\\:@,\\\\\\\\]+)\\\\1(?>[^\' . $end . \']*)\' . $end;\n"
	"                    } else {\n"
	"                        $regex = $begin . $tagName . \'\\b(?>(?:(?!\' . $name . \'=).)*)\\b\' . $name . \'=([\\\'\\\"])(?P<name>[\\$\\w\\-\\/\\.\\:@,\\\\\\\\]+)\\\\1(?>(?:(?!\' . $end . \').)*)\' . $end;\n"
	"                    }\n"
	"                    break;\n"
	"            }\n"
	"        }\n"
	"        return \'/\' . $regex . \'/is\';\n"
	"    }\n"
	"}\n"
	"\n"
;
#endif